package com.sunfeng.commonlib.polling;

import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Message;

import com.sunfeng.commonlib.message.CommonMessage;
import com.sunfeng.commonlib.message.CommonMessageManager;
import com.sunfeng.commonlib.receiver.CommonScreenReceiver;

import java.util.HashMap;
import java.util.Map;


public class PollingHelper {
    private static PollingHelper instance;
    private IntentFilter screenFilter;
    private Application application;
    private Map<Integer, PollingModel> pollingMap = new HashMap<>();
    private CommonScreenReceiver screenReceiver;

    private PollingHelper(Application application) {
        this.application = application;
        CommonMessageManager.getInstance().registerObserver(this);
        registerScreenChangeReceiver();
    }

    public static PollingHelper getInstance(Application application) {
        if (instance == null) {
            instance = new PollingHelper(application);
        }
        return instance;
    }

    private final Handler mAlarmHandler = new Handler(new Handler.Callback() {
        public boolean handleMessage(Message msg) {
            try {
                PollingModel model = (PollingModel) msg.obj;
                Intent intent = new Intent(application, model.getCls());
                intent.setAction(model.getAction_name());
                intent.putExtra("from", "handler");
                application.startService(intent);
                reStartPollingHandler(model,msg.what);
            }catch (Exception e){
                e.printStackTrace();
            }
            return false;
        }
    });

    private void registerScreenChangeReceiver() {
        screenFilter = new IntentFilter();
        screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
        screenFilter.addAction(Intent.ACTION_SCREEN_ON);
        screenReceiver = new CommonScreenReceiver();
        registerReceiver(screenReceiver, screenFilter);
    }

    /**
     *
     * @param delayMillis 延迟执行的秒数
     * @param intervalMillis 轮询时间间隔
     * @param serviceClass 轮询启动的service
     * @param action_name intent的 ActionName
     * @param msgWhat 轮询的标识id
     */
    public void startPolling( int delayMillis, int intervalMillis, Class<?> serviceClass, String action_name, int msgWhat) {
        PollingModel pollingModel = new PollingModel(action_name, serviceClass, delayMillis, intervalMillis);
        if (!pollingMap.containsKey(msgWhat)) {
            pollingMap.put(msgWhat, pollingModel);
        }
        if (Util.isScreenOn(application)) {
            setPollingHandler(pollingModel, msgWhat);
        } else {
            PollingAlarmServiceUtil.startPollingService(application, delayMillis, intervalMillis, serviceClass, action_name);
        }
    }

    public void stopPolling() {
        stopPollingHandler();
        if (pollingMap != null) {
            for (Integer key : pollingMap.keySet()) {
                PollingModel model = pollingMap.get(key);
                if (model != null) {
                    PollingAlarmServiceUtil.stopPollingService(application, model.cls, model.action_name);
                }
            }
        }
        unregisterReceiver(screenReceiver);
        CommonMessageManager.getInstance().unRegisterObserver(this);
    }

    /**
     * 初始化轮询handler，并执行第一次轮询
     * @param model PollingModel
     * @param message 轮询的标识id
     */
    public void setPollingHandler(PollingModel model, int message) {
        cancelPollingHandler(message);
        //handler轮询
        Message msg = new Message();
        msg.obj = model;
        msg.what = message;
        mAlarmHandler.sendMessageDelayed(msg, model.getDelayMillis() * 1000);
    }

    /**
     * handler 轮询一次以后，继续通过 handler 轮询
     * @param model PollingModel
     * @param message 轮询的标识id
     */
    public void reStartPollingHandler(PollingModel model, int message){
        cancelPollingHandler(message);
        Message msg = new Message();
        msg.obj = model;
        msg.what = message;
        mAlarmHandler.sendMessageDelayed(msg, model.getIntervalMillis() * 1000);
    }

    public void cancelPollingHandler(int message) {
        mAlarmHandler.removeMessages(message);
    }

    public void stopPollingHandler() {
        mAlarmHandler.removeCallbacksAndMessages(null);
    }

    public void onEvent(CommonMessage event) {
        if (null != event) {
            switch (event.getType()) {
                case SCREEN_OFF:
                    if (pollingMap == null) {
                        return;
                    }
                    for (Integer key : pollingMap.keySet()) {
                        cancelPollingHandler(key);
                    }
                    for (Integer key : pollingMap.keySet()) {
                        PollingModel pollingModel = pollingMap.get(key);
                        if (pollingModel != null) {
                            PollingAlarmServiceUtil.startPollingService(application, pollingModel.getDelayMillis(), pollingModel.intervalMillis
                                    , pollingMap.get(key).getCls(), pollingMap.get(key).getAction_name());
                        }
                    }
                    break;
                case SCREEN_ON:
                    for (Integer key : pollingMap.keySet()) {
                        PollingModel pollingModel = pollingMap.get(key);
                        if (pollingModel != null) {
                            PollingAlarmServiceUtil.stopPollingService(application, pollingMap.get(key).getCls(), pollingMap.get(key).getAction_name());
                            setPollingHandler(pollingModel, key);
                        }
                    }
                    break;
                default:
                    break;
            }
        }
    }

    public void registerReceiver(final BroadcastReceiver broadcastReceiver, final IntentFilter intentFilter) {
        Util.runSafe(new Runnable() {
            @Override
            public void run() {
                application.registerReceiver(broadcastReceiver, intentFilter);
            }
        });
    }

    public void unregisterReceiver(BroadcastReceiver broadcastReceiver) {
        try {
            if (broadcastReceiver != null) {
                application.unregisterReceiver(broadcastReceiver);
            }
        } catch (Exception e) {
        }
    }
}
